﻿using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace AESDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            string key = string.Empty;
            string iv = string.Empty;

            // aes256 代表 key为256位,转为byte是32 iv为128,转为byte是16
            // utf8 英文数字占1byte8位,中文占3byte24位
            Console.WriteLine($"1:{Encoding.UTF8.GetBytes("1").Length}");
            Console.WriteLine($"a:{Encoding.UTF8.GetBytes("a").Length}");
            Console.WriteLine($",:{Encoding.UTF8.GetBytes(",").Length}");
            Console.WriteLine($"，:{Encoding.UTF8.GetBytes("，").Length}");
            Console.WriteLine($"中:{Encoding.UTF8.GetBytes("中").Length}");
            Console.WriteLine($"");

            // 自定义：可以用英文数字半角符号设置32byte密码
            key = "1234567890abcdefghijklmnopqrstuv";
            iv = "1234567890123456";

            string text = "加解密";
            byte[] encrypt = Program.EncryptAES(text, Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv));
            string encryptText = Convert.ToBase64String(encrypt);
            Console.WriteLine(encryptText);
            byte[] decrypt = Convert.FromBase64String(encryptText);
            Console.WriteLine(Program.DecryptAES(decrypt, Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv)));
            Console.WriteLine($"");

            // 自动生成然后记录
            using (var aes = Aes.Create())
            {
                Console.WriteLine($"[默认]Mode:{aes.Mode},Padding:{aes.Padding},KeySize:{aes.KeySize},BlockSize:{aes.BlockSize}");
                Console.WriteLine($"");

                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.KeySize = 128;
                aes.BlockSize = 128;
                aes.GenerateKey();
                aes.GenerateIV();
                Console.WriteLine($"[CBC,PKCS7]key:{Convert.ToBase64String(aes.Key)},keyLen:{aes.Key.Length},iv:{Convert.ToBase64String(aes.IV)},ivLen:{aes.IV.Length}");
                Console.WriteLine($"");

                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.KeySize = 256;
                aes.GenerateKey();
                aes.GenerateIV();
                Console.WriteLine($"[CBC,PKCS7]key:{Convert.ToBase64String(aes.Key)},keyLen:{aes.Key.Length},iv:{Convert.ToBase64String(aes.IV)},ivLen:{aes.IV.Length}");
                Console.WriteLine($"");

                key = Convert.ToBase64String(aes.Key);
                iv = Convert.ToBase64String(aes.IV);

            }

            text = "加解密2={a:\"test\",b:123}";
            encrypt = Program.EncryptAES(text, Convert.FromBase64String(key), Convert.FromBase64String(iv));
            encryptText = Convert.ToBase64String(encrypt);
            Console.WriteLine(encryptText);
            decrypt = Convert.FromBase64String(encryptText);
            Console.WriteLine(Program.DecryptAES(decrypt, Convert.FromBase64String(key), Convert.FromBase64String(iv)));
            Console.WriteLine($"");


            Console.ReadKey();
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="text">加密前文本</param>
        /// <param name="key">AES Key</param>
        /// <param name="iv">AES IV</param>
        /// <returns>加密后文本</returns>
        public static byte[] EncryptAES(string text, byte[] key, byte[] iv)
        {
            byte[] encrypted;
            using (var aes = Aes.Create())
            {
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.Key = key;
                aes.IV = iv;

                // 创建加密器
                var encryptor = aes.CreateEncryptor();

                // 创建内存流
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    // 创建加密流并和内存流关联
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        // 加密流创建流写入器
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            // 将需要加密的文本写入加密流
                            swEncrypt.Write(text);
                        }
                        // 将内存流中的数据转成byte数组
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            return encrypted;
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="cipherText">加密数据byte数组</param>
        /// <param name="key">AES Key</param>
        /// <param name="iv">AES IV</param>
        /// <returns>解密后字符串</returns>
        public static string DecryptAES(byte[] cipherText, byte[] key, byte[] iv)
        {
            string result = string.Empty;
            using (var aes = Aes.Create())
            {
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.Key = key;
                aes.IV = iv;

                // 创建解密器
                var decryptor = aes.CreateDecryptor();

                // 把加密的byte数组加入到内存流内
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    // 把内存流对象放入加密流对象中并解密
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        // 读取加密流内数据
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // 转成string
                            result = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return result;
        }


    }
}
